#pragma once

#include "LsysBranchRule.h"
#include "atlimage.h"

#include "DrawableWidget.h"
// CImage

class LsysGa
{
	CImage * m_pImgCompare;

	CImage * m_pTmpImage;
public:
	struct PopulationElement : public ICustomDraw
	{
		LsysBranchRule m_BranchRule;
		ParamVector * m_arrParamVectors;
		double m_lfFitness;
		bool m_bFitnessDetermined;

		PopulationElement();
		~PopulationElement();

		virtual void Draw();

		void Creep(PopulationElement & Src, double lfCreepWidth);

		void CrossOver(PopulationElement & Src1, double lfWeight1, PopulationElement & Src2, double lfWeight2);


		const PopulationElement & operator=(const PopulationElement &src);
	};
private:

	CDrawableWidget * m_pDrawWidget;

	PopulationElement * m_arrCurrentPop;
	PopulationElement * m_arrNextPop;
	PopulationElement * m_arrCrossoverResults;
	PopulationElement * m_arrMutationResults;

	PopulationElement m_CurrBest;

	int m_nPopSize, m_nNumMutants, m_nNumOffspring;

	void InitArrays();

	double Evaluate(PopulationElement * pEvalMe);

	void EvaluatePopulation(PopulationElement *, int nSize);

	void DoCrossOver();

	void DoCreep();

	void IterateOneGeneration();

	void SelectBest(PopulationElement * pArr1, int nSize1, PopulationElement * pArr2, int nSize2);
public:
	LsysGa(void);
	LsysGa(int nPopSize, int nMutants, int nOffspring);

	void SetDrawWidget(CDrawableWidget * pWidget);

	void SetPopParams(int nPopSize, int nMutants, int nOffspring)
	{
		m_nPopSize = nPopSize; m_nNumMutants = nMutants; m_nNumOffspring = nOffspring;
	}

	virtual ~LsysGa(void);

	void SetImgCompare(CImage * pImage) { m_pImgCompare = pImage; }

	void Train(int nGenerations);
};
